package cm.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @author: yxh
 * @Description: URL调用
 * @Date: Created in 2023/1/4 15:01
 * @Modified By:
 */
@Slf4j
@Component
public class HttpClientUtil {
    private static CloseableHttpClient httpClient;

    private static final int CONNECTION_TIMEOUT = 3000;

    private static final int SOCKET_TIMEOUT = 3000;

    private static final int DEFAULT_MAX_PER_TOTAL = 10;

    private static final int MAX_TOTAL = 100;

    static {
        try {
            // 并发设置
            PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager();
            manager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_TOTAL);
            manager.setMaxTotal(MAX_TOTAL);
            // 超时设置
            RequestConfig defaultConfig = RequestConfig.custom().setConnectTimeout(CONNECTION_TIMEOUT).setConnectionRequestTimeout(SOCKET_TIMEOUT).setConnectionRequestTimeout(CONNECTION_TIMEOUT).build();
            httpClient = HttpClients.custom().setConnectionManager(manager).setDefaultRequestConfig(defaultConfig).build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 通过post的形式发送消息
     *
     * @param url
     * @param jsonObject
     * @author chenwu on 2023.12.25
     */
    public static String sendRequestByPostType(String url, JSONObject jsonObject) throws IOException {
        return sendRequestByPostTypeWithToken(url, jsonObject, null);
    }

    public static String sendRequestByPostTypeWithToken(String url, JSONObject jsonObject, String token) throws IOException {
        HttpPost httpPost = new HttpPost(url);

        StringEntity entity = new StringEntity(jsonObject.toString());
        //指定请求编码方式
        entity.setContentEncoding("utf-8");
        //数据格式
        entity.setContentType("application/json");
        httpPost.setEntity(entity);

        // header参数封装
        if (token != null) {
            httpPost.setHeader("Authorization", "Bearer " + token);
        }

        //发送请求
        CloseableHttpResponse response = httpClient.execute(httpPost);

        //解析返回结果
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new IOException("post request for url:" + url + ",jsonObject=" + jsonObject + " is not successful by statusCode:" + statusCode);
        }
        HttpEntity entity1 = response.getEntity();
        String responseBody = EntityUtils.toString(entity1);
        System.out.println("url=" + url + ",jsonObject=" + jsonObject + ",responseBody=" + responseBody);
        //关闭资源
        response.close();
        return responseBody;
    }

    /**
     * 发送get请求
     *
     * @return {@link String}
     * @author chenwu on 2023.12.26
     */
    public static String sendRequestByGetType(String url) throws IOException {
        HttpGet httpGet = new HttpGet(url);
        return sendGetRequest(url, httpGet);
    }

    public static String sendRequestByGetTypeWithToken(String url, String token) throws IOException {
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Token", token);
        return sendGetRequest(url, httpGet);
    }

    private static String sendGetRequest(String url, HttpGet httpGet) throws IOException {
        CloseableHttpResponse response = httpClient.execute(httpGet);
        StatusLine statusLine = response.getStatusLine();
        if (statusLine.getStatusCode() != 200) {
            throw new IOException("get request for url:" + url);
        }
        HttpEntity entity = response.getEntity();
        String responseBody = EntityUtils.toString(entity);
        response.close();
        return responseBody;
    }

    public static String sendRequestByPost(String url,JSONObject jsonObject) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        StringEntity entity = new StringEntity(jsonObject.toString(),"utf-8");
        httpPost.addHeader("content-type", "application/json; charset=UTF-8");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Accept-Encoding", "UTF-8");
        httpPost.setEntity(entity);
        //发送请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        //解析返回结果
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode != 200) {
            throw new IOException("post request for url:" + url + ",jsonObject=" + jsonObject + " is not successful by statusCode:" + statusCode);
        }
        HttpEntity entity1 = response.getEntity();
        String responseBody = EntityUtils.toString(entity1);
        System.out.println("url=" + url + ",jsonObject=" + jsonObject + ",responseBody=" + responseBody);
        //关闭资源
        response.close();
        return responseBody;
    }
    /**
     * @param url   地址
     * @param param 参数
     * @param token url携带的headers（非必须）
     * @return java.lang.Object
     * @Description: get方式
     * @author yxh
     * @date 2023/1/5
     */
    public JSONObject requestGetUrl(String url, Map<String, String> param, String token) throws Exception {
        // 设置完整的url
        URIBuilder uriBuilder = new URIBuilder(url);
        if (param != null){
            //添加参数
            for (Map.Entry<String, String> entry : param.entrySet()) {
                uriBuilder.setParameter(entry.getKey(), entry.getValue());
            }
        }
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.addHeader("Content-Type", "application/json");
        if (token != null) {
            httpGet.addHeader("token", token);
        }
        RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).build();
        httpGet.setConfig(config);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpGet);
        //状态码
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            HttpEntity entity = response.getEntity();
            String string = EntityUtils.toString(entity, "UTF-8");
            JSONObject jsonObject = JSONObject.parseObject(string);
            return jsonObject;
        }else {
            throw new HttpResponseException(statusCode, "响应异常");
        }
    }

    /**
     * @param url   : 地址
     * @param param : 参数
     * @param token : url携带的headers（非必须）
     * @return java.lang.Object
     * @Description: post方式获取访问url接口
     */
    public Object requestPostUrl(String url, Map<String, Object> param, String token) throws Exception {
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "application/json");
        if (token != null) {
            httpPost.addHeader("token", token);
        }
        // 设置请求的参数
        JSONObject jsonParam = new JSONObject();
        param.forEach((k, v) -> jsonParam.put(k, v));
        StringEntity stringEntity = new StringEntity(jsonParam.toString(), StandardCharsets.UTF_8);
        stringEntity.setContentEncoding("UTF-8");
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);
        RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).build();
        httpPost.setConfig(config);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            HttpEntity entity = response.getEntity();
            String string = EntityUtils.toString(entity, "UTF-8");
            JSONObject jsonObject = JSONObject.parseObject(string);
            return jsonObject;
        }else {
            throw new HttpResponseException(statusCode, "响应异常");
        }
    }

}
